/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * AllocationOfHoursPanel.java
 *
 * Created on 09-Mar-2011, 22:18:43
 */

package TimeRecording.forms;

import TimeRecording.business.DaisyChainUtilities;
import TimeRecording.forms.renderers.HoursCellRenderer;
import TimeRecording.forms.renderers.TableRowHeaderRenderer;
import TimeRecording.tables.AllocationOfHours;
import java.awt.Color;
import java.awt.Component;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

/**
 *
 * @author david
 */
public class AllocationOfHoursPanel extends javax.swing.JPanel {

    private class TwoDoubles {

        private Double value;
        private Double comparison;

        public TwoDoubles(Double value, Double comparison) {
            this.value = value;
            this.comparison = comparison;
        }

        public Double getValue() {
            return value;
        }

        public boolean isDifferent() {
            return !DaisyChainUtilities.nullAwareDoublesEqual(value, comparison);
        }
    }
    
    private class ColouredHoursCellRenderer extends HoursCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column) {

            TwoDoubles values = null;
            JLabel component = null;

            if (value instanceof TwoDoubles) {
                values = (TwoDoubles)value;
                component = (JLabel)super.getTableCellRendererComponent(
                        table, values.getValue(), isSelected, hasFocus, row, column);
            } else {
                component = (JLabel)super.getTableCellRendererComponent(
                        table, values, isSelected, hasFocus, row, column);
            }

            if (values != null && values.isDifferent()) {
                component.setForeground(Color.blue);
            } else {
                component.setForeground(table.getForeground());
            }
            
            return component;
        }
    }

    // <editor-fold defaultstate="collapsed" desc="TableModel">
    private class AllocationTableModel extends DefaultTableModel {

        private final static int TOTAL_ROW = 0;
        private final static int FIXED_ROW = 1;
        private final static int SEMI_FLEXI_ROW = 2;
        private final static int FLEXI_ROW = 3;
        private final static int SESSIONAL_ROW = 4;
        private final static int AD_HOC_ROW = 5;

        private final static int EXPECTED_COL = 0;
        private final static int RECORDED_COL = 1;
        private final static int HOLIDAY_COL = 2;
        private final static int SICKNESS_COL = 3;
        private final static int VARIANCE_COL = 4;

        private final String[] HEADINGS = new String[] {
                "Expected", "Recorded", "Holiday", "Sickness", "Variance"};

        private AllocationOfHours hours;
        private AllocationOfHours comparison;

        @Override
        public int getColumnCount() {
            return 5;
        }

        @Override
        public int getRowCount() {
            return 6;
        }

        @Override
        public String getColumnName(int column) {
            return HEADINGS[column];
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }

        @Override
        public Object getValueAt(int row, int column) {

            if (hours == null) {
                return "";
            }
            
            switch (row) {

                case TOTAL_ROW:
                    switch (column) {
                        case EXPECTED_COL:
                            return new TwoDoubles(
                                    hours.getExpected(),
                                    comparison.getExpected());
                        case RECORDED_COL:
                            return new TwoDoubles(
                                    hours.getRecorded() - hours.getHoliday(),
                                    comparison.getRecorded() - comparison.getHoliday());
                        case HOLIDAY_COL:
                            return new TwoDoubles(
                                    hours.getHoliday(),
                                    comparison.getHoliday());
                        case SICKNESS_COL:
                            return new TwoDoubles(
                                    hours.getSickness(),
                                    comparison.getSickness());
                        case VARIANCE_COL:
                            return new TwoDoubles(
                                    hours.getRecorded() - hours.getExpected(),
                                    comparison.getRecorded() - comparison.getExpected());
                        default:
                            return null;
                    }

                case FIXED_ROW:
                    switch (column) {
                        case EXPECTED_COL:
                            return new TwoDoubles(
                                    hours.getFixedExpected(),
                                    comparison.getFixedExpected());
                        case RECORDED_COL:
                            return new TwoDoubles(
                                    hours.getFixedRecorded() -
                                            hours.getFixedHoliday(),
                                    comparison.getFixedRecorded() -
                                            comparison.getFixedHoliday());
                        case HOLIDAY_COL:
                            return new TwoDoubles(
                                    hours.getFixedHoliday(),
                                    comparison.getFixedHoliday());
                        case SICKNESS_COL:
                            return new TwoDoubles(
                                    hours.getFixedSickness(),
                                    comparison.getFixedSickness());
                        case VARIANCE_COL:
                            return new TwoDoubles(
                                    hours.getFixedRecorded() -
                                            hours.getFixedExpected(),
                                    comparison.getFixedRecorded() -
                                            comparison.getFixedExpected());
                        default:
                            return null;
                    }

                case SEMI_FLEXI_ROW:
                    switch (column) {
                        case EXPECTED_COL:
                            return new TwoDoubles(
                                    hours.getSemiFlexiExpected(),
                                    comparison.getSemiFlexiExpected());
                        case RECORDED_COL:
                            return new TwoDoubles(
                                    hours.getSemiFlexiRecorded() -
                                            hours.getSemiFlexiHoliday(),
                                    comparison.getSemiFlexiRecorded() -
                                            comparison.getSemiFlexiHoliday());
                        case HOLIDAY_COL:
                            return new TwoDoubles(
                                    hours.getSemiFlexiHoliday(),
                                    comparison.getSemiFlexiHoliday());
                        case SICKNESS_COL:
                            return new TwoDoubles(
                                    hours.getSemiFlexiSickness(),
                                    comparison.getSemiFlexiSickness());
                        case VARIANCE_COL:
                            return new TwoDoubles(
                                    hours.getSemiFlexiRecorded() -
                                            hours.getSemiFlexiExpected(),
                                    comparison.getSemiFlexiRecorded() -
                                            comparison.getSemiFlexiExpected());
                        default:
                            return null;
                    }

                case FLEXI_ROW:
                    switch (column) {
                        case EXPECTED_COL:
                            return new TwoDoubles(
                                    hours.getFlexiExpected(),
                                    comparison.getFlexiExpected());
                        case RECORDED_COL:
                            return new TwoDoubles(
                                    hours.getFlexiRecorded() -
                                            hours.getFlexiHoliday(),
                                    comparison.getFlexiRecorded() -
                                            comparison.getFlexiHoliday());
                        case HOLIDAY_COL:
                            return new TwoDoubles(
                                    hours.getFlexiHoliday(),
                                    comparison.getFlexiHoliday());
                        case SICKNESS_COL:
                            return new TwoDoubles(
                                    hours.getFlexiSickness(),
                                    comparison.getFlexiSickness());
                        case VARIANCE_COL:
                            return new TwoDoubles(
                                    hours.getFlexiRecorded() -
                                            hours.getFlexiExpected(),
                                    comparison.getFlexiRecorded() -
                                            comparison.getFlexiExpected());
                        default:
                            return null;
                    }

                case SESSIONAL_ROW:
                    switch (column) {
                        case EXPECTED_COL:
                            return new TwoDoubles(
                                    hours.getSessionExpected(),
                                    comparison.getSessionExpected());
                        case RECORDED_COL:
                            return new TwoDoubles(
                                    hours.getSessionRecorded() -
                                            hours.getSessionHoliday(),
                                    comparison.getSessionRecorded() -
                                            comparison.getSessionHoliday());
                        case HOLIDAY_COL:
                            return new TwoDoubles(
                                    hours.getSessionHoliday(),
                                    comparison.getSessionHoliday());
                        case SICKNESS_COL:
                            return new TwoDoubles(
                                    hours.getSessionSickness(),
                                    comparison.getSessionSickness());
                        case VARIANCE_COL:
                            return new TwoDoubles(
                                    hours.getSessionRecorded() -
                                            hours.getSessionExpected(),
                                    comparison.getSessionRecorded() -
                                            comparison.getSessionExpected());
                        default:
                            return null;
                    }

                case AD_HOC_ROW:
                    switch (column) {
                        case EXPECTED_COL:
                            return new TwoDoubles(0.0, 0.0);
                        case RECORDED_COL:
                            return new TwoDoubles(
                                    hours.getAdHocRecorded() -
                                            hours.getAdHocHoliday(),
                                    comparison.getAdHocRecorded() -
                                            comparison.getAdHocHoliday());
                        case HOLIDAY_COL:
                            return new TwoDoubles(
                                    hours.getAdHocHoliday(),
                                    comparison.getAdHocHoliday());
                        case SICKNESS_COL:
                            return new TwoDoubles(
                                    hours.getAdHocSickness(),
                                    comparison.getAdHocSickness());
                        case VARIANCE_COL:
                            return new TwoDoubles(
                                    hours.getAdHocRecorded(),
                                    comparison.getAdHocRecorded());
                        default:
                            return null;
                    }

                default:
                    return null;
            }
        }

        public void setHours(AllocationOfHours hours) {
            this.hours = hours;
        }

        public void setComparison(AllocationOfHours comparison) {
            this.comparison = comparison;
        }
    }
    // </editor-fold>

    private ColouredHoursCellRenderer hoursRenderer =
            new ColouredHoursCellRenderer();
    
    private AllocationOfHours allocationOfHours;
    private AllocationOfHours comparisonHours;

    public AllocationOfHours getAllocationOfHours() {
        return allocationOfHours;
    }

    public void setAllocationOfHours(AllocationOfHours allocationOfHours) {

        AllocationOfHours oldAllocationOfHours = this.allocationOfHours;
        this.allocationOfHours = allocationOfHours;
        tableModel.setHours(allocationOfHours);
        tableModel.fireTableDataChanged();
        firePropertyChange("allocationOfHours",
                oldAllocationOfHours, allocationOfHours);
    }

    public AllocationOfHours getComparisonHours() {
        return comparisonHours;
    }

    public void setComparisonHours(AllocationOfHours comparisonHours) {

        AllocationOfHours oldComparisonHours = this.comparisonHours;
        this.comparisonHours = comparisonHours;
        tableModel.setComparison(comparisonHours);
        tableModel.fireTableDataChanged();
        firePropertyChange("comparisonHours",
                oldComparisonHours, comparisonHours);
    }

    private AllocationTableModel tableModel = new AllocationTableModel();

    /** Creates new form AllocationOfHoursPanel */
    public AllocationOfHoursPanel() {
        
        initComponents();

        JList rowHeader = new JList(new String[] {
                "Total",
                "Allocated to Fixed Hours",
                "Allocated to Weekly Flexi",
                "Allocated to Full Flexi",
                "Allocated to Sessional",
                "Allocated to Ad Hoc"});

        rowHeader.setFixedCellWidth(150);
        rowHeader.setFixedCellHeight(
                allocationTable.getRowHeight());
        rowHeader.setCellRenderer(
                new TableRowHeaderRenderer(allocationTable));
        rowHeader.setBackground(allocationTable.getTableHeader().getBackground());

        allocationTablePane.setRowHeaderView(rowHeader);
        allocationTable.setModel(tableModel);

        allocationTable.getColumnModel().getColumn(0).setCellRenderer(hoursRenderer);
        allocationTable.getColumnModel().getColumn(1).setCellRenderer(hoursRenderer);
        allocationTable.getColumnModel().getColumn(2).setCellRenderer(hoursRenderer);
        allocationTable.getColumnModel().getColumn(3).setCellRenderer(hoursRenderer);
        allocationTable.getColumnModel().getColumn(4).setCellRenderer(hoursRenderer);
    }

    public void showHoursAndMinutes(boolean show) {
        hoursRenderer.showHoursAndMinutes(show);
        allocationTable.repaint();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        allocationTablePane = new javax.swing.JScrollPane();
        allocationTable = new javax.swing.JTable();

        setName("Form"); // NOI18N
        setLayout(new java.awt.GridBagLayout());

        allocationTablePane.setName("allocationTablePane"); // NOI18N

        allocationTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null}
            },
            new String [] {
                "", "Expected", "Recorded", "Holiday", "Sickness", "Variance"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.Object.class, java.lang.Double.class, java.lang.Double.class, java.lang.Double.class, java.lang.Double.class, java.lang.Double.class
            };
            boolean[] canEdit = new boolean [] {
                false, false, false, false, false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        allocationTable.setName("allocationTable"); // NOI18N
        allocationTablePane.setViewportView(allocationTable);
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(TimeRecording.TimeRecordingApp.class).getContext().getResourceMap(AllocationOfHoursPanel.class);
        allocationTable.getColumnModel().getColumn(0).setHeaderValue(resourceMap.getString("allocationTable.columnModel.title0")); // NOI18N
        allocationTable.getColumnModel().getColumn(1).setHeaderValue(resourceMap.getString("allocationTable.columnModel.title1")); // NOI18N
        allocationTable.getColumnModel().getColumn(2).setHeaderValue(resourceMap.getString("allocationTable.columnModel.title2")); // NOI18N
        allocationTable.getColumnModel().getColumn(3).setHeaderValue(resourceMap.getString("allocationTable.columnModel.title4")); // NOI18N
        allocationTable.getColumnModel().getColumn(4).setHeaderValue(resourceMap.getString("allocationTable.columnModel.title3")); // NOI18N
        allocationTable.getColumnModel().getColumn(5).setHeaderValue(resourceMap.getString("allocationTable.columnModel.title5")); // NOI18N

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        add(allocationTablePane, gridBagConstraints);
    }// </editor-fold>//GEN-END:initComponents


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTable allocationTable;
    private javax.swing.JScrollPane allocationTablePane;
    // End of variables declaration//GEN-END:variables

}
